import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Stream.of;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ExportReportPdf {

	private static final File pdfOutDir = new File("/tmp/report_export_dir");

	public static void main(String[] args) {
		ExecutorService executorService = Executors.newFixedThreadPool(20);
		String active = System.getProperty("spring.profiles.active");

		System.out.println(active);
		System.out.println(System.getenv("spring.profiles.active"));
		System.out.println("Hello world");

		String env = "testhy";
		String reportType = "AntiFraudSample";
		String id = "8a2132686dcd037f016dcd1efdc8000a";

		int count = 20;
		List<Future<ExportResult>> fs = new ArrayList<>(count);
		List<ExportResult> ess = new ArrayList<>(count);
		Future<ExportResult> f = null;
		for (int i = 0; i < count; i++) {
			ess.add(new ExportResult(env, reportType, id));
			f = executorService.submit(ess.get(i));
			fs.add(f);
		}
		// 等待10秒
		try {
			executorService.shutdown();
			if (executorService.awaitTermination(100, TimeUnit.SECONDS) == false) {
				executorService.shutdownNow();
			}
		} catch (InterruptedException e1) {
		}
		System.out.println("begin: " + LocalDateTime.now());
		ExportResult exportResult = null;
		List<ExportResult> doneResults = new ArrayList<>(count); // 按时完成的结果
		List<ExportResult> timeoutResults = new ArrayList<>(count); // 超时的结果
		for (int i = 0; i < count; i++) {
			try {
				f = fs.get(i);
				if (f.isDone()) {
					exportResult = f.get();
					doneResults.add(exportResult);
					System.out.println("导出是否成功：" + exportResult.isSuccess());
				} else {
					exportResult = ess.get(i);
					timeoutResults.add(exportResult);
					System.out.println("未完成的任务：" + exportResult);
				}
			} catch (InterruptedException | ExecutionException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		try {
			File zipfile = zipFile(doneResults, timeoutResults);

			System.out.println("导出pdf结束" + zipfile);
		} catch (Exception e) {
			e.printStackTrace();
		}

		System.out.println("end: " + LocalDateTime.now());
	}

	private static File zipFile(List<ExportResult> doneResults, List<ExportResult> timeoutResults)
			throws FileNotFoundException, IOException {
		StringBuilder errorMsg = new StringBuilder();

		if (timeoutResults.isEmpty() == false) {
			errorMsg.append("\n导出超时的报告：");
			errorMsg.append(timeoutResults.stream().map(t -> t.getId()).collect(joining("、")));
		}
		List<ExportResult> failResults = doneResults.stream().filter(t -> t.isSuccess() == false).collect(toList());
		if (failResults.isEmpty() == false) {
			errorMsg.append("\n导出失败的报告：");
			errorMsg.append(failResults.stream().map(t -> t.getId()).collect(joining("、")));
		}

		List<ExportResult> successResults = doneResults.stream().filter(t -> t.isSuccess()).collect(toList());

		File zipPath = new File(pdfOutDir, of(UUID.randomUUID().toString(), ".zip").collect(joining()));
		try (FileOutputStream fos = new FileOutputStream(zipPath); ZipOutputStream zop = new ZipOutputStream(fos);) {
			ZipEntry entry = null;
			String name = null;
			if (successResults.isEmpty() == false) {
				byte[] buffer = new byte[1024];
				int readByte = 0;
				for (ExportResult er : successResults) {
					name = of(er.getId(), "_", UUID.randomUUID().toString(), ".pdf").collect(joining());
					entry = new ZipEntry(name);
					zop.putNextEntry(entry);

					FileInputStream fis = new FileInputStream(new File(er.getPdfPath()));
					while ((readByte = fis.read(buffer)) >= 0) {
						zop.write(buffer, 0, readByte);
					}
					fis.close();
				}
			}
			if (errorMsg.length() > 0) {
				name = "error.txt";
				entry = new ZipEntry(name);
				zop.putNextEntry(entry);
				zop.write(errorMsg.toString().getBytes(StandardCharsets.UTF_8));
			}

		}

		return zipPath;
	}
}
